package com.sojoys.artifact.plugin.event;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.jfinal.plugin.IPlugin;
import com.sojoys.artifact.annotation.IEventType;
import com.sojoys.artifact.constant.ConfigConstant;
import com.sojoys.artifact.manager.PropManager;
import com.xiaoleilu.hutool.util.ClassUtil;

/**
 * 类 EventService 的实现描述：TODO 类实现描述
 * 
 * @author ligh4 2015年3月16日下午4:42:40
 */
public class EventPlugin implements IPlugin{

	private ConcurrentLinkedQueue<Event> events = new ConcurrentLinkedQueue<Event>();
	private ConcurrentHashMap<String, IEventCallback> eventCallbacks = new ConcurrentHashMap<String, IEventCallback>();
	private ConcurrentHashMap<Integer, List<IEventListener>> eventHandlers = new ConcurrentHashMap<Integer, List<IEventListener>>();
//	private ThreadPoolExecutor threadPool = new ThreadPoolExecutor(4, 10, 5000, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());

	private boolean stopped = false;
	private Thread eventsConsumeThread;

	private static EventPlugin instance = new EventPlugin();

	private EventPlugin() {
	}
	
	@Override
	public boolean start() {
		// 扫描Listeners
		instance.scanListeners();
		
		instance.eventsConsumeThread = new Thread(new Runnable() {
			@Override
			public void run() {
				instance.consumeEvents();
			}
		});
		instance.eventsConsumeThread.start();
		return true;
	}
	@Override
	public boolean stop() {
		instance.stopped = true;
//		instance.threadPool.shutdown();
		return true;
	}

	public static void fireEvent(Event event) {

		instance.events.add(event);
	}

	public static void fireEvent(Event event, IEventCallback callback) {
		instance.eventCallbacks.put(event.getId(), callback);
		fireEvent(event);
	}

	/**
	 * 注册EventHandler
	 * @param eventType
	 * @param handler
	 */
	public static void registerEventListener(int eventType, IEventListener handler) {
		List<IEventListener> handlers = instance.eventHandlers.get(eventType);
		if (handlers == null) {
			handlers = new ArrayList<IEventListener>();
			instance.eventHandlers.put(eventType, handlers);
		}

		handlers = instance.eventHandlers.get(eventType);
		handlers.add(handler);
	}

	
	private void consumeEvents() {
		while (!stopped) {
			if (!events.isEmpty()) {
				Event event = events.poll();
				Object result = null;
				List<IEventListener> handlers = eventHandlers.get(event.getType());
				for (IEventListener handler : handlers) {
					result = handler.onEvent(event);
				}

				IEventCallback callback = eventCallbacks.get(event.getId());
				if (callback != null) {
					eventCallbacks.remove(event.getId());
					callback.onEventFinished(event, result);
				}
			}
		}
	}

	private void scanListeners() {
		
//		Set<Class<?>> scanClasses = ClassUtil.scanPackageBySuper(PropManager.get(ConfigConstant.CONFIG_SCAN_LISTENER),IEventListener.class);
//		for (Class scanClass : scanClasses) {
//			if (scanClass.isInterface()) {
//				continue;
//			}
//			IEventType eventType = (IEventType) scanClass.getAnnotation(IEventType.class);
//			Object listener = ClassUtil.newInstance(scanClass);
//			registerEventListener(eventType.value(), (IEventListener) listener);
//		}
	}
}
